package org.wxd.bi.controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wxd.aop.Aop;
import org.wxd.append.StreamAppend;
import org.wxd.batis.EntityField;
import org.wxd.batis.sql.SqlDataWrapper;
import org.wxd.batis.sql.SqlEntityTable;
import org.wxd.bi.api.struct.PushColumn;
import org.wxd.bi.api.struct.PushMapping;
import org.wxd.bi.data.AppFactory;
import org.wxd.bi.data.AppService;
import org.wxd.bi.data.InnerDbWork;
import org.wxd.format.IdFormat;
import org.wxd.lang.RunResult;
import org.wxd.net.controller.ann.TextController;
import org.wxd.net.controller.ann.TextMapping;
import org.wxd.net.web.hs.HttpSession;
import org.wxd.net.web.hs.controller.cmd.HttpSignCheck;
import org.wxd.str.json.Json2Object;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author: Troy.Chen(無心道, 15388152619)
 * @version: 2021-09-29 13:35
 **/
@TextController(url = "push")
public class PushController implements Serializable, HttpSignCheck {

    private static final long serialVersionUID = 1L;
    private static final Logger log = LoggerFactory.getLogger(PushController.class);

    private IdFormat idFormat = IdFormat.build();
    private static final Integer ZeroInteger = 0;
    private static final Long ZeroLong = 0L;

    @Resource
    private AppFactory appFactory;
    @Resource
    private InnerDbWork innerDbWork;

    @Override
    @TextMapping(remarks = "登录检查")
    public boolean checkSign(StreamAppend out, JSONObject params, HttpSession session) throws Exception {
        AppService appService = Aop.getBean(AppFactory.class).dataService(params);
        if (appService == null || !params.getString("token").equals(appService.getAppInfo().getAppToken())) {
            return false;
        }
        return true;
    }

    @TextMapping(remarks = "删除映射信息")
    public RunResult removeMapping(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        String tableName = params.getString("tableName");
        appService.getAppDataHelper().dropTable(tableName);
        PushMapping remove = appService.getDataMappingMap().remove(tableName);
        return RunResult.ok().putData(tableName, remove != null);
    }

    @TextMapping(remarks = "映射信息")
    public RunResult mapping(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        String mapping = params.getString("mapping");
        PushMapping pushMapping = Json2Object.parseObject(mapping, PushMapping.class);
        if (pushMapping.getColumnList().stream().noneMatch(v -> PushColumn.ID.getName().equalsIgnoreCase(v.getName()))) {
            pushMapping.getColumnList().add(0, PushColumn.ID.clone());
        }

        if (pushMapping.getColumnList().stream().noneMatch(v -> PushColumn.SAVE_TIME.getName().equalsIgnoreCase(v.getName()))) {
            pushMapping.getColumnList().add(1, PushColumn.SAVE_TIME.clone());
        }

        if (pushMapping.getShowIndex() < 100) {
            pushMapping.setShowIndex(pushMapping.getShowIndex() + 100);
        }

        pushMapping.sortColumn();
        SqlEntityTable sqlEntityTable = pushMapping.mapping();
        appService.getAppDataHelper().createTable(sqlEntityTable);
        appService.getAppDataHelper().replace(pushMapping);
        appService.getDataMappingMap().put(pushMapping.getTableName(), pushMapping);
        return RunResult.ok().putData(pushMapping.getTableName(), true);
    }

    @TextMapping(remarks = "上传数据")
    public RunResult data(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        String tableName = params.getString("tableName");
        String data = params.getString("data");
        LinkedHashMap<String, Object> map = Json2Object.parseObjectTR(data, new TypeReference<LinkedHashMap<String, Object>>() {
        });
        String pushMsg = innerDb(appService, tableName, map);
        return RunResult.ok().setData(pushMsg);
    }

    @TextMapping(remarks = "上传数据")
    public RunResult datas(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        String tableName = params.getString("tableName");
        String datas = params.getString("datas");
        LinkedList<String> dataList = Json2Object.parseObjectTR(datas,
                new TypeReference<LinkedList<String>>() {
                });

        List<String> r = new LinkedList<>();
        for (String data : dataList) {
            LinkedHashMap<String, Object> map = Json2Object.parseObjectTR(data, new TypeReference<LinkedHashMap<String, Object>>() {
            });
            r.add(innerDb(appService, tableName, map));
        }

        return RunResult.ok().setData(r);
    }

    public String innerDb(AppService appService, String tableName, Map<String, Object> data) throws Exception {
        PushMapping pushMapping = appService.getDataMappingMap().get(tableName);
        if (pushMapping == null) {
            return "表 " + tableName + " 未注册";
        }
        SqlEntityTable sqlEntityTable = pushMapping.mapping();
        SqlDataWrapper<SqlEntityTable> dataWrapper = appService.getAppDataHelper().getDataWrapper();
        JSONObject jsonObject = new JSONObject(true);
        Object id = data.remove(PushColumn.ID.getName());
        if (id == null || id.equals(0) || id.equals(0L)) {
            id = idFormat.getId();
        }

        {
            EntityField idColumn = sqlEntityTable.getDataColumnKey();
            Object toDbValue = dataWrapper.toDbValue(idColumn, id);
            jsonObject.put(PushColumn.ID.getName(), toDbValue);
        }

        Object saveTime = data.remove(PushColumn.SAVE_TIME.getName());
        if (saveTime == null || saveTime.equals(0) || saveTime.equals(0L)) {
            saveTime = System.currentTimeMillis();
        }

        {
            EntityField saveTimeColumn = sqlEntityTable.getColumnMap().get(PushColumn.SAVE_TIME.getName());
            Object toDbValue = dataWrapper.toDbValue(saveTimeColumn, saveTime);
            jsonObject.put(PushColumn.SAVE_TIME.getName(), toDbValue);
        }

        if (!data.containsKey(PushColumn.EXPAND.getName())) {
            jsonObject.put(PushColumn.EXPAND.getName(), "");
        }

        for (Map.Entry<String, Object> entry : data.entrySet()) {
            jsonObject.put(entry.getKey(), dataWrapper.toDbValue(sqlEntityTable.getColumnMap().get(entry.getKey()), entry.getValue()));
        }

        innerDbWork.addInner(appService.getAppInfo().getAppId(), sqlEntityTable, jsonObject);
        return "表 " + tableName + " ok";
    }

}
